home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
BBS-Archive
/
Comm
/
AmiTCP30b2.lha
/
src
/
util
/
ls
/
sort.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-24
|
3KB
|
117 lines
/* $Id: sort.c,v 1.1 1993/09/17 06:24:05 ppessi Exp $
*
* sort.c -- sort a table using quicksort
*
* Author: ppessi <Pekka.Pessi@hut.fi>
*
* Copyright (c) 1992 Pekka Pessi
* All rights reserved
*
* Created : Thu Dec 3 11:21:42 1992 ppessi
* Last modified: Thu Dec 3 11:57:51 1992 ppessi
*
*/
#ifdef NOMYDEBUG
#define MYDEBUG( x )
#else
#include <clib/dos_protos.h>
#define MYDEBUG(x) x
#endif
static void
_quick_sort(void *slots[], int left, int right, int(*compare)(void *, void *))
{
void *ld, *rd, *md, *sd;
int middle, l, r;
remove_tail:
if (right - left < 8) /* we left this for insertion sort */
return;
/* Find median */
middle = (left + right) / 2;
ld = slots[left];
md = slots[middle];
rd = slots[right];
MYDEBUG( FPrintf(Stderr,
"Left (%ld): %s, middle (%ld): %s, right (%ld): %s\n",
left, ld -> ed_Name,
middle, md -> ed_Name,
right, rd -> ed_Name) );
if ((compare)(ld, rd) > 0)
sd = rd, rd = ld, ld = sd; /* swap */
if ((compare)(ld, md) > 0)
sd = md, md = ld, ld = sd; /* swap */
if ((compare)(md, rd) > 0)
sd = md, md = rd, rd = sd; /* swap */
slots[right] = rd;
slots[middle] = slots[right - 1];
slots[left] = ld;
/* use median as a sentinel and partitioning element */
slots[right - 1] = md;
MYDEBUG( FPrintf(Stderr, "Left: %s, middle: %s, right: %s\n",
ld -> ed_Name, md -> ed_Name, rd -> ed_Name) );
for (l = left, r = right - 1; l < r; ) {
/* scan from left */
do {l++;} while ((compare)(md, slots[l]) >= 0);
MYDEBUG( FPrintf(Stderr, "Left %s \n", slots[l] -> ed_Name) );
/* scan from right */
do {r--;} while ((compare)(slots[r], md) >= 0);
MYDEBUG( FPrintf(Stderr, "Right %s \n", slots[r] -> ed_Name) );
if (l < r)
ld = slots[l], slots[l] = slots[r], slots[r] = ld; /* swap elements */
}
/* move partition element into partition place */
md = slots[right - 1], slots[right - 1] = slots[l], slots[l] = md;
if (l > middle) { /* sort smaller partition recursively */
_quick_sort(slots, l + 1, right, compare);
right = l - 1;
} else {
_quick_sort(slots, left, l - 1, compare);
left = l + 1;
}
goto remove_tail; /* remove tail recursion */
}
/*
Actual quick_sort does final sorting with insertion sort
*/
void
quick_sort(void *slots[], int size, int(*compare)(void *, void *))
{
register int i, j;
MYDEBUG( register int distance; )
register void *data;
_quick_sort(slots, 0, size- 1, compare);
for (j = 1; j < size; j++) {
data = slots[j];
i = j;
MYDEBUG( distance = 0; )
while (i > 0 && (compare)(data, slots[i-1]) < 0) {
slots[i] = slots[i-1];
i--;
MYDEBUG( distance++; )
}
slots[i] = data;
MYDEBUG( if (distance)
FPrintf(Stderr, "Moved %s by %ld\n", data -> ed_Name, distance); )
}
}